<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - interactive - voxel painter</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		
	</head>
	<body id="body">

		

		<script src="libs/three.js"></script>

		<script src="libs/Detector.js"></script>

		<script src="libs/OrbitControls.js"></script>
		<script src="libs/hilbert2D.js"></script>

		<script src="libs/hilbert3D.js"></script>

		<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>







		<script>

			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

			var camera, scene, renderer;
			var plane, cube;
			var mouse, raycaster, isShiftDown = false;

			var rollOverMesh, rollOverMaterial;
			var cubeGeo, cubeMaterial;

			var objects = [];
			var voxels = []
			var earth_raduis = 180

			var cubeMap={}
			var objects=[]
			var hilbert3DIt =3


			//var points2d = hilbert2D( new THREE.Vector3( 0, 0, 0 ), width, it )

			var points = hilbert3D( new THREE.Vector3( 0, 0, 0 ), earth_raduis, hilbert3DIt, 0, 1, 2, 3, 4, 5, 6, 7 )
			var	cubeLen = (earth_raduis*2)/Math.pow(points.length,1/3)


			var it = Math.log(points.length)/Math.log(4)-1
			var width = cubeLen*Math.sqrt(Math.pow(4,it+1))/2
			var points2d = hilbert2D( new THREE.Vector3( 0, -earth_raduis, 0 ), width, it )



			var indexIn2d = 0


		    var cubeGeo = new THREE.BoxBufferGeometry( cubeLen, cubeLen, cubeLen );



			init();
			render();
			show3dHilbertCurve(points)
			//show2dHilbertCurve(points2d)
			//animate();
			
			

			function init() {

				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 100000 );
				camera.position.set( 0, 1000, 1000 );
				camera.lookAt( new THREE.Vector3() );

				scene = new THREE.Scene();
				scene.background = new THREE.Color( 0x000000 );
			
				//objects.push( plane );

				// lights

				var ambientLight = new THREE.AmbientLight( 0x606060 );
				scene.add( ambientLight );

				var directionalLight = new THREE.DirectionalLight( 0xffffff );
				directionalLight.position.set( 1, 0.75, 0.5 ).normalize();
				scene.add( directionalLight );

				renderer = new THREE.WebGLRenderer( { antialias: true } );
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				document.body.appendChild( renderer.domElement );

				//

				window.addEventListener( 'resize', onWindowResize, false );

				var controls = new THREE.OrbitControls( camera, renderer.domElement);
				controls.minDistance = 2;
				controls.maxDistance = 100000;
				controls.maxPolarAngle = Math.PI;

				render();
			}

			function show3dHilbertCurve(points){
				// 3d lines
				// 3d points length:8^(n+1)
				var geometry3 = new THREE.Geometry()
				var colors3 = [];

				for ( var i = 0; i < points.length; i ++ ) {

					geometry3.vertices.push( points[ i ] );

					colors3[ i ] = new THREE.Color( 0xffffff );
					colors3[ i ].setHSL( i / points.length, 1, 0.5 );

				}

				geometry3.colors = colors3;

				// lines

				var material = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 3, vertexColors: THREE.VertexColors } );

				var line3d = new THREE.Line( geometry3, material );
				//line3d.scale.set( 0.4, 0.4, 0.4 );
				line3d.position.set( 0, 0, 0 );
				scene.add( line3d );
			}

			function show2dHilbertCurve(points){
				var geometry2 = new THREE.Geometry()
				var colors2 = []


				for ( var i = 0; i < points.length; i ++ ) {

					geometry2.vertices.push( points[ i ] );

					colors2[ i ] = new THREE.Color( 0xffffff );
					colors2[ i ].setHSL( i / points.length, 1, 0.5 );

				}

				geometry2.colors = colors2;

				
				// lines

				var material = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 3, vertexColors: THREE.VertexColors } );

				

				var line2d = new THREE.Line( geometry2, material );
				line2d.position.set( 0, -2, 0 );
				scene.add( line2d );
			}


			function createInnerEarth(){
				//createEarth

				var whiteMaterial= new THREE.MeshPhongMaterial({
					color:0xffffff,//三角面颜色
					//side:THREE.DoubleSide//两面可见
				});
				var yellowMaterial= new THREE.MeshPhongMaterial({
					color:0xffff00,//三角面颜色
					//side:THREE.DoubleSide//两面可见
				});

				var orangeMaterial= new THREE.MeshPhongMaterial({
					color:0xFFA500,//三角面颜色
					//side:THREE.DoubleSide//两面可见
				});

				var redMaterial= new THREE.MeshPhongMaterial({
					color:0xF75000,//三角面颜色
					//side:THREE.DoubleSide//两面可见
				});
				var darkRedMaterial= new THREE.MeshPhongMaterial({
					color:0xCE0000,//三角面颜色
					//side:THREE.DoubleSide//两面可见
				});
				var crustMaterial= new THREE.MeshPhongMaterial({
					color:0x333333,//三角面颜色
					//side:THREE.DoubleSide//两面可见
				});

				var shellMaterial= new THREE.MeshPhongMaterial({
					color:0x0033ff,//三角面颜色
					//side:THREE.DoubleSide//两面可见
				});
				function getInnerKenalMaterial(){
					var r = Math.floor(Math.random()*10)
					if(r<3){
						return whiteMaterial
					}else{
						return yellowMaterial

					}

				}

				function getOutKenalMaterial(){
					var r = Math.floor(Math.random()*10)
					if(r<1){
						return whiteMaterial
					}else if(r<4){
						return yellowMaterial
					}else{
						return orangeMaterial

					}

				}

				function getLowMantleMaterial(){
					var r = Math.floor(Math.random()*10)
					if(r<2){
						return orangeMaterial
					}else{
						return redMaterial
					}

				}

				function getUpperMantleMaterial(sqaure_dis){
					
					return crustMaterial

					

				}

				function getCrustMaterial(){
					return crustMaterial
				}


				for(var i=0;i<points.length;i++){
					var point = points[i]
					var x = point.x
					var y = point.y
					var z = point.z
					var sqaure_dis = Math.pow(x,2)+Math.pow(y,2)+Math.pow(z,2)
					var voxel = null
					var add2Scene = true
					if(sqaure_dis < Math.pow(earth_raduis*0.215,2)){
						voxel = new THREE.Mesh( cubeGeo, getInnerKenalMaterial() );
					}else if(sqaure_dis < Math.pow(earth_raduis*(0.215+0.33),2)){
						voxel = new THREE.Mesh( cubeGeo, getOutKenalMaterial() );
					}else if(sqaure_dis < Math.pow(earth_raduis*(0.215+0.33+0.32),2)){
						voxel = new THREE.Mesh( cubeGeo, getLowMantleMaterial() );
						
					}else if(sqaure_dis < Math.pow(earth_raduis*(0.215+0.33+0.32+0.1),2)){
						voxel = new THREE.Mesh( cubeGeo, getUpperMantleMaterial(sqaure_dis) );	
					}else if(sqaure_dis < Math.pow(earth_raduis,2)){
						voxel = new THREE.Mesh( cubeGeo, getCrustMaterial() );
					}else{
						voxel = new THREE.Mesh( cubeGeo, shellMaterial );
						add2Scene = false
					}
					if(cubeMap[x+":"+y+":"+z]){//地壳已经包含
						continue

					}
					if(voxel){
						voxel.position.set(x,y,z)
						objects.push( voxel );
						voxels.push(voxel)
						// if(add2Scene&&z<0){//z<0 for half
						// 	scene.add( voxel );
						// }
						if(add2Scene){
							scene.add( voxel );
						}
					}
					cubeMap[x+":"+y+":"+z] = voxel


				}

			}

			function createEarthShell(points){
				
				for(var i=0;i<points.length;i++){
					var point = points[i]
					// if(point['z']>0){
					// 	continue
					// }
				

					var color = point['color']
					var shellMaterial= new THREE.MeshPhongMaterial({
						color:color,//三角面颜色
						//side:THREE.DoubleSide//两面可见
					});

					var voxel = new THREE.Mesh( cubeGeo, shellMaterial );
					voxel.position.set(point['x'],point['y'],point['z'])
					objects.push( voxel );
					voxels.push(voxel)
					scene.add( voxel );
					cubeMap[point['x']+":"+point['y']+":"+point['z']] = voxel
				}
				
			}



			function loadModels(){



				 $.get("earth_shell_3it.json", function(result,status){
				 	if(result == "file not found"){
				 		alert("加载地壳模型异常！")

				 	}else{
					    var points = result//JSON.parse(result)
					    createEarthShell(points)
					    createInnerEarth()
						animate()
						//transDim()
						



				 	}
				   
				 })
			}
			loadModels()

			function onWindowResize() {

				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();

				renderer.setSize( window.innerWidth, window.innerHeight );

			}



			function render() {

				renderer.render( scene, camera );

			}

			var actionStep = 0


		
			
			var theta = 0
			var alpha = 0.5
			function animate() {
				
				render();
				requestAnimationFrame( animate );
				

				moveCamera()

				if(actionStep == 0){
					add2dCurve()
				}else{
					moveCube()
				}

				//moveCube()
			}	
			var pushIndex = 0
			function add2dCurve(){
				if(pushIndex>=points2d.length-1){
					actionStep = 1
					return
				}
				var geometry2 = new THREE.Geometry()
				var colors2 = []


				//for ( var i = 0; i < points.length; i ++ ) {

				geometry2.vertices.push( points2d[ pushIndex ] );
				geometry2.vertices.push( points2d[ pushIndex+1 ] );


				colors2[ 0 ] = new THREE.Color( 0xffffff );
				colors2[ 1 ] = new THREE.Color( 0xffffff );

				colors2[ 0 ].setHSL( pushIndex / points.length, 1, 0.5 );
				colors2[ 1 ].setHSL( (pushIndex+1) / points.length, 1, 0.5 );


				//}

				geometry2.colors = colors2;

				
				// lines

				var material = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 3, vertexColors: THREE.VertexColors } );

				

				var line2d = new THREE.Line( geometry2, material );
				line2d.position.set( 0, 0, 0 );
				scene.add( line2d );
				pushIndex++

			}

			function moveCamera(){
				var r = 2200
				var cz = r*Math.sin(alpha)*Math.sin(theta)
				var cx = r*Math.sin(alpha)*Math.cos(theta)
				var cy = r*Math.cos(alpha)

				theta-=0.001
				//alpha+=0.001

				
			
				camera.position.set(cx,cy,cz)
				camera.lookAt(0,-650,0)
				camera.rotateOnWorldAxis(new THREE.Vector3(0,1,0),0.001)

			}

			function moveCube(){
				for (var i=0;i<points.length-1;i++){
					var point = points[i]
		        	var voxel = cubeMap[point.x+":"+point.y+":"+point.z]

		        	var nextPoint = points[i+1]
		        	var nextVoxel = cubeMap[nextPoint.x+":"+nextPoint.y+":"+nextPoint.z]

		        	voxel.position.copy(nextVoxel.position)


		        }
		        var lastIndex = points.length-1
	   			var lastPoint = points[lastIndex]
	   			var lastVoxel = cubeMap[lastPoint.x+":"+lastPoint.y+":"+lastPoint.z]


	   			var copyVec = new THREE.Vector3()
	   			copyVec.copy(points2d[indexIn2d])

	   			var distance = copyVec.sub(lastVoxel.position)
	   			if(distance.length()<cubeLen){
	   				lastVoxel.position.copy(points2d[indexIn2d])
	   				indexIn2d++

	   			}else{
	   				var step = distance.normalize().multiplyScalar(cubeLen)
	   				lastVoxel.position.add(step)
	   			}
	   			


			}


			function transDim(){
				for (var i=0;i<points.length-1;i++){
					var point = points[i]
		        	var voxel = cubeMap[point.x+":"+point.y+":"+point.z]
		        	var point2d = points2d[i]

		        	voxel.position.x = point2d.x
		        	voxel.position.y = point2d.y

		        	voxel.position.z = point2d.z


		        }

			}

			

		</script>

	</body>
</html>
